package org.frank.blockchain.p2p.server;


import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.json.JSONUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.frank.blockchain.domain.Command;
import org.frank.blockchain.domain.NetAddress;
import org.frank.blockchain.util.ClientMap;
import org.frank.blockchain.util.Constants;
import org.frank.blockchain.util.InvokeUtil;

import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class ManagerServerHandler extends ChannelInboundHandlerAdapter {
    ByteBuf buff;

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        Command command = (Command)msg;
        Object instance = ReflectUtil.newInstance(command.getClassName());
        if (ObjectUtil.isEmpty(instance)) {
            return;
        }
        Command p2pResponse = InvokeUtil.invoke(command);
        String valueJson = JSONUtil.toJsonStr(p2pResponse);
        valueJson += Constants.END_CHAR;
        ChannelFuture future = ctx.writeAndFlush(Unpooled.wrappedBuffer(valueJson.getBytes()));
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        SocketAddress remote = ctx.channel().remoteAddress();
        SocketAddress local = ctx.channel().localAddress();
        if (!ClientMap.getInstance().containsKey(remote.toString())) {
            NetAddress address = new NetAddress();
            address.setLocal(local);
            address.setRemote(remote);
            ClientMap.getInstance().put(remote.toString(), address);
        }
        System.out.println(ctx.channel().remoteAddress() + " register");
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        SocketAddress address = ctx.channel().remoteAddress();
        if (ClientMap.getInstance().containsKey(address.toString())) {
            ClientMap.getInstance().remove(address.toString());
        }
        System.out.println(ctx.channel().remoteAddress() + " unregister");
        super.channelInactive(ctx);
    }
}
